﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace WSServer
{
    public class WSSocketMessagePool
    {
        const int MONITOR_DURATION = 180 * 1000;
        const int MESSAGE_CACHE_THREASHOLD = 100;
        static object locker = new object();
        private List<WSResponse> responses { get; set; }
        private Timer messageMonitor { get; set; }
        public string poolId { get; set; }

        public WSSocketMessagePool(string _poolId)
        {
            poolId = _poolId;
            responses = new List<WSResponse>();
            messageMonitor = new Timer((o) =>
            {
                WSStorage storage = new WSStorage("socket_cache");
                this.CacheResponsesToStorage(storage);
            }, null, MONITOR_DURATION, MONITOR_DURATION);
        }
        public int Count 
        {
            get
            {
                return responses.Count;
            }
        }
        public WSResponse GetFirstResponse()
        {
            var pool = responses.Where((resp) =>
            {
                return resp.status == WSResponseStatus.kWSResponseStatusPendingSend;
            });
            if (pool.Count() > 0)
                return pool.First();
            return null;
        }
        public void didReceiveMessageRecip(WSRequest receipRequest)
        {
            if (receipRequest.message_type == WSSocketReceiveMessageType.kSocketRecvMessageTypeRecvRecip)
            {
                responses.RemoveAll(r => r.messageId == receipRequest.state);
            }
        }
        public void addMessage(WSResponse response)
        {
            lock(locker)
            {
                responses.Add(response);
            }
        }
        public void CacheResponsesToStorage(WSStorage storage)
        {
            lock(locker)
            {
                responses.RemoveAll(r => r.status == WSResponseStatus.kWSResponseStatusReceipRecved);
                
                var responsesOnStorage = cachedResponses(new WSStorage("socket_storage"));
                responsesOnStorage.AddRange(responses);
                if(storage.store(responsesOnStorage.Distinct().ToList(), poolId))
                {
                    responses.Clear();
                }
            }
        }
        public void RestoreResponsesToStorage(WSStorage storage,WSAccessToken token)
        {
            lock(locker)
            {
                List<WSResponse> _responses = storage.loadFromStorage(poolId);
                if (_responses != null)
                {
                    _responses.ForEach(r =>
                        {
                            r.status = WSResponseStatus.kWSResponseStatusPendingSend;
                            r.token = token;
                        });
                    this.responses.AddRange(_responses);
                }
                storage.cleanup(poolId);
            }
        }
        private List<WSResponse> cachedResponses(WSStorage storage)
        {
            List <WSResponse> responsesOnStorage = storage.loadFromStorage(poolId);
            if (responsesOnStorage != null)
                return responsesOnStorage;
            else
                return new List<WSResponse>();
        }
    }
}
